home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / program / 441 / sc_desk / ccd / ccd.c next >
C/C++ Source or Header  |  1990-11-23  |  29KB  |  940 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. static  char    Version[] =
  13. "\r\nccd: version 1.01d  Copyright (c) 1988 by Sozobon, Limited.";
  14.  
  15. /*
  16.  * ccd - C compiler driver program (for GEM)
  17.  *
  18.  * Parses command line for options and file names, then calls the
  19.  * various passes of the compiler as needed.  
  20.  * 
  21.  * v1.01d - 11/05/88 Ian Lepore.
  22.  *          This version is somewhat more 'desktop friendly'.  If the
  23.  *          program is started without any command-line parms, it will
  24.  *          prompt for them interactively.   This helps get around the
  25.  *          small input line in the .TTP parms dialog. This hack also goes 
  26.  *          around desktop's (and some shells') nasty habit of uppercasing
  27.  *          all command-line parms by lowercasing everything arbitrarily,
  28.  *          and using the '-z' switch to invoke the optimizer instead of
  29.  *          the normal '-O' switch.
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <fcntl.h>
  34. #include <osbind.h>
  35. #include <ctype.h>
  36.  
  37. /*
  38.  * This is the amount of space to grab from TOS at a time for
  39.  * malloc(). The default is 64K which wastes space if you don't
  40.  * need much. Since we spawn sub-programs from cc, it's important
  41.  * to leave as much memory for them as possible.
  42.  */
  43. long    _BLKSIZ = 4096;
  44.  
  45. #ifndef TRUE
  46. #define FALSE   (0)
  47. #define TRUE    !FALSE
  48. #endif
  49.  
  50. #define MAXOPT  16      /* max. number of options to any one pass */
  51.  
  52. /*
  53.  * Standard filename extensions
  54.  */
  55. #define EXSUF   ".ttp,.tos,.prg"        /* suffixes for executables */
  56. #define LIBSUF  ".a,.lib"               /* libraries */
  57.  
  58. /*
  59.  * Compiler pass information
  60.  */
  61. #define CC      "hcc"
  62.  
  63. char    *hccopt[MAXOPT];
  64. int     hcc_cnt = 0;            /* number of options to hcc */
  65.  
  66. /*
  67.  * Optimizer information
  68.  */
  69. #define OPT     "top"
  70. #define OTMP    "top_tmp.s"
  71.  
  72. /*
  73.  * Assembler information
  74.  */
  75. #define ASM     "jas"                   /* default assembler */
  76. #define ASMD    "as68symb.dat"          /* assembler data file (as68 only) */
  77.  
  78. /*
  79.  * Loader information
  80.  */
  81. #define LD      "ld"
  82. #define LTMP    "ldfile.tmp"            /* loader command file */
  83.  
  84. #define CSU     "dstart.o"              /* C startup code */
  85. #define PCSU    "pdstart.o"             /* profiling startup code */
  86.  
  87. #define LIBC    "dlibs"                 /* C runtime library */
  88. #define PLIBC   "pdlibs"                /* profiled runtime library */
  89.  
  90. #define LIBM    "libm"                  /* math library */
  91. #define PLIBM   "plibm"                 /* profiled math library */
  92.  
  93. /*
  94.  * Path information
  95.  */
  96.  
  97. char    *path;          /* where to find executables */
  98. char    *lib;           /* where to find library stuff */
  99. char    *tmp;           /* where to put temporary files */
  100.  
  101. /*
  102.  * Default paths for executables and libraries
  103.  *
  104.  * Always check the root of the current drive first.
  105.  */
  106. #define DEFPATH         "\\bin,\\sozobon\\bin"
  107. #define DEFLIB          "\\lib,\\sozobon\\lib"
  108. #define DEFTMP          ""
  109.  
  110. /*
  111.  * Boolean options
  112.  */
  113. int     mflag = 0;      /* generate a load map */
  114. int     vflag = 0;      /* show what we're doing w/ version numbers */
  115. int     nflag = 0;      /* ...but don't really do it */
  116. int     Sflag = 0;      /* generate assembly files */
  117. int     cflag = 0;      /* generate ".s" files only */
  118. int     Oflag = 0;      /* run the optimizer */
  119. int     tflag = 0;      /* generate a symbol table in executables */
  120. int     pflag = 0;      /* enable execution profiling */
  121. int     fflag = 0;      /* enable floating point */
  122.  
  123. /*
  124.  * We build lists of the various file types we're given. Within each
  125.  * type, MAXF says how many we can deal with.
  126.  */
  127. #define MAXF    30
  128.  
  129. int     ncfiles = 0;    /* .c files */
  130. char    *cfiles[MAXF];
  131. int     nsfiles = 0;    /* .s files */
  132. char    *sfiles[MAXF];
  133. int     nofiles = 0;    /* .o files */
  134. char    *ofiles[MAXF];
  135. int     nlfiles = 0;    /* .a or .lib files (or files with no suffix) */
  136. char    *lfiles[MAXF];
  137.  
  138. char    *output = NULL; /* output file */
  139.  
  140. /*-------------------------------------------------------------------------
  141.  * added/changed for v1.01d
  142.  *------------------------------------------------------------------------*/
  143. #define MAXCMDV 64
  144. char    cmdln[130];     /* Command image passed to compiler pieces.       */
  145. char    cmdinp[255];    /* Interactive keyin command buffer.              */
  146. char    *cmdv[MAXCMDV]; /* cmdv/cmdc = argv/argc.  Made global to make the*/
  147. int     cmdc;           /* command input source transparent to main logic.*/
  148. /*-------------------------------------------------------------------------
  149.  * end of v1.01d changes
  150.  *------------------------------------------------------------------------*/
  151.  
  152. myexit(n)
  153. int     n;
  154. {
  155.         fprintf(stderr, "<Press RETURN to continue>\n");
  156.         while (getchar() != '\n')
  157.                 ;
  158.         exit(n);
  159. }
  160.  
  161. mklower(s)
  162. register char   *s;
  163. {
  164.         for (; *s ;s++) {
  165.                 if (isupper(*s))
  166.                         *s = tolower(*s);
  167.         }
  168. }
  169.  
  170. usage()
  171. {
  172.         fprintf(stderr,
  173.                 "\nSozobon C Compiler Options:\n");
  174.         fprintf(stderr,
  175.                 "-C             compile, but don't link\n");
  176.         fprintf(stderr,
  177.                 "-Z             run the assembly code optimizer\n");
  178.         fprintf(stderr,
  179.                 "-S             don't assemble, leave .s files around\n");
  180.         fprintf(stderr,
  181.                 "-V             show the passes and versions as they run\n");
  182.         fprintf(stderr,
  183.                 "-N             like -v, but don't really run anything\n");
  184.         fprintf(stderr,
  185.                 "-M             tell the loader to generate a load map\n");
  186.         fprintf(stderr,
  187.                 "-T             tell the loader to generate a symbol table\n");
  188.         fprintf(stderr,
  189.                 "-F             link the floating point library\n");
  190.         fprintf(stderr,
  191.                 "-P             enable execution profiling\n");
  192.         fprintf(stderr,
  193.                 "-O f           use the file 'f' for the loader output\n");
  194.         fprintf(stderr,
  195.                 "-Ilib          add dir. 'lib' to the header search list\n");
  196.         fprintf(stderr,
  197.                 "-Dsym          define the pre-processor symbol 'sym' as 1\n");
  198.         fprintf(stderr,
  199.                 "-Dsym=val      or as 'val'\n");
  200.         fprintf(stderr,
  201.                 "-Usym          un-define the built-in symbol 'sym'\n");
  202.  
  203. }
  204.  
  205. /*-------------------------------------------------------------------------
  206.  *
  207.  * Begin v1.01d hack code to make 'cc' desktop-friendly.
  208.  *
  209.  *  (You'll see a decidedly different (read: un-unix) programming style
  210.  *   in here.  Specifically, you won't find yourself 42 levels deep in 
  211.  *   function calls before you hit a line of code that *does* something).
  212.  *-----------------------------------------------------------------------*/
  213.  
  214. /*---------------------------------------------------------------------
  215.  * Copy 'count' strings pointed to by elements in the array 'pointers'
  216.  * into the interactive-keyin command line buffer.  As each string is
  217.  * copied, save a pointer to it into the 'cmdv' array.  ('cmdv' takes the
  218.  * place of 'argv' in the code found in 'main()').  Upon exit, cmdc
  219.  * will count the count of cmdv array elements.
  220.  *-------------------------------------------------------------------*/
  221.  
  222. cmd_copy(count, pointers)
  223. int     count;
  224. char    *pointers[];
  225. {
  226.         char    *p_wrk1, 
  227.                 *p_wrk2;
  228.  
  229.         p_wrk1 = cmdinp;
  230.         for (cmdc = 0; cmdc < count; cmdc++)
  231.                 {
  232.                 cmdv[cmdc] = p_wrk1;
  233.                 p_wrk2 = pointers[cmdc];
  234.                 while (*p_wrk1++ = *p_wrk2++)
  235.                         {}
  236.                 }          
  237. }
  238.  
  239. /*-------------------------------------------------------------------------
  240.  *
  241.  * Note to self: included from \ian\libi\bldargv.c 
  242.  *
  243.  * BldArgv --  Scan a string, setting pointers to the space-delimited
  244.  *             words within it.  Null terminate each word except the
  245.  *             last (which should already be null terminated, anyway).
  246.  *             Strip leading spaces from the args (that is...point
  247.  *             past them).
  248.  *
  249.  *   Usage:
  250.  *        Pass this routine a pointer to an array which will hold
  251.  *        the pointers to the arguments, a pointer to the string buffer,
  252.  *        and the maximum number of pointers your array can hold. It
  253.  *        will return the number of pointers generated.  Note that if
  254.  *        there are more words in the buffer than you have pointer slots
  255.  *        for, the last pointer will be to the remainder of the buffer.
  256.  *
  257.  *        Confused?  Check this out:
  258.  *
  259.  *             char string[] = "    c:\test.prg   arga   argb   argc"
  260.  *             char *argv[3];
  261.  *             numargs = bldargv(argv,string,3);
  262.  *
  263.  *        This sequence will yield the following:
  264.  *
  265.  *             numargs = 3
  266.  *             argv[0] -> "c:\test.prg"
  267.  *             argv[1] -> "arga"
  268.  *             argv[2] -> "argb   argc"
  269.  *
  270.  *        Note that the leading spaces were removed from the arguments,
  271.  *        but the imbedded spaces within the 'rest of the buffer' 3rd
  272.  *        arg were left intact.
  273.  *
  274.  * Maintenance:
  275.  *  04/13/87 - Original version. 
  276.  *
  277.  *------------------------------------------------------------------------*/
  278.  
  279. bldargv(argv, p_strbuf, maxarg)
  280. register char *argv[], *p_strbuf;
  281. int  maxarg;
  282. {
  283.         int  argc;
  284.  
  285.         argc = 0;
  286.         while(*p_strbuf)
  287.                 {
  288.                 while (*p_strbuf == ' ')
  289.                         p_strbuf++;
  290.                 if (*p_strbuf)
  291.                         {
  292.                         argv[argc++] = p_strbuf;
  293.                         while (*p_strbuf && (*p_strbuf != ' '))
  294.                                 p_strbuf++;
  295.                         if (*p_strbuf == ' ')
  296.                                 *p_strbuf++ = 0x00;
  297.                         if (argc == maxarg)
  298.                                 return(argc);
  299.                         }
  300.                 }
  301. return(argc);
  302. }
  303.  
  304. /*-------------------------------------------------------------------------
  305.  * ask() - Read line from std input, convert to normal str, return length. 
  306.  *  Note that this uses the native DOS function Cconrs() to get the string.
  307.  *  If the user has redirected I/O in some way, we don't want the machine
  308.  *  to lock up, we want to be able to talk with the user...
  309.  *------------------------------------------------------------------------*/
  310.  
  311. ask(str,maxlen)
  312. register char *str;
  313. int  maxlen;
  314. {
  315.         register int  length,counter;
  316.         register char *p_wrk1, *p_wrk2;
  317.  
  318.         *str = (char)maxlen;
  319.         Cconrs(str);
  320.         Cconws("\r\n"); /* hack: fixes bug in TurboST 'Cconrs' hook. */
  321.         length = counter = (int)*(str+1);
  322.         p_wrk2 = 2 + (p_wrk1 = str);
  323.         while (counter--)
  324.                 *p_wrk1++ = *p_wrk2++;
  325.         *p_wrk1 = 0x00;
  326.         return(length);
  327. }
  328.  
  329. /*-------------------------------------------------------------------------
  330.  * interactive_input - Ask the user for the parms, parse them into args.
  331.  *  Note that this uses the native DOS function Cconws() for output.
  332.  *  If the user has redirected I/O in some way, we don't want the machine
  333.  *  to lock up, we want to be able to talk with the user...
  334.  *  (Oh yuck, it has a 'goto' in it...)
  335.  *------------------------------------------------------------------------*/
  336.  
  337. interactive_input()
  338. {
  339. reprompt:
  340.         Cconws("\r\nccd: Enter command line, '?' for help, <CR> to exit...\r\n");
  341.  
  342.         if (0 == ask(cmdinp, sizeof(cmdinp)))
  343.                 myexit(1);                      /* exit on <CR> */
  344.  
  345.         if (cmdinp[0] == '?')
  346.                 {
  347.                 usage();                        /* show help if requested */
  348.                 goto reprompt;                  /* then prompt again. */
  349.                 }
  350.  
  351.         cmdc = 1 + bldargv(&cmdv[1], cmdinp, MAXCMDV); 
  352. }
  353.  
  354. /*-------------------------------------------------------------------------
  355.  *
  356.  * End of v1.01d desktop-friendly hack.  
  357.  *  We now return you to your regularly-scheduled program...
  358.  *
  359.  *-----------------------------------------------------------------------*/
  360.  
  361. main(argc, argv)
  362. int     argc;
  363. char    *argv[];
  364. {
  365.         extern  char    *chsuf();
  366.         register int    i;
  367.         register char   *s;
  368.         register int    endopt;
  369.         int     domsg = FALSE;
  370.  
  371. /*------------------------------------------------------------------------
  372.  * added for v1.01d
  373.  *-----------------------------------------------------------------------*/
  374.         if (argc == 1)                  /* if no cmdlin args, prompt     */
  375.                 interactive_input();    /* user for them interactively,  */
  376.         else                            /* else copy cmdlin args to      */
  377.                 cmd_copy(argc, argv);   /* global buffer/pointer array.  */
  378. /*------------------------------------------------------------------------
  379.  * end of v1.01d changes
  380.  *-----------------------------------------------------------------------*/
  381.  
  382.         for (i=1; i < cmdc ;i++) {
  383.                 mklower(cmdv[i]);       /* v1.01d: force arg to lowercase */
  384.                 if (cmdv[i][0] == '-') {        /* option */ 
  385.                         endopt = FALSE;
  386.                         for (s = &cmdv[i][1]; *s && !endopt ;s++) {
  387.                                 switch (*s) {
  388.                                 case 'c':
  389.                                 case 'C':
  390.                                         cflag = TRUE; break;
  391.                                 case 'Z':
  392.                                 case 'z':
  393.                                         Oflag = TRUE; break;
  394.                                 case 'S':
  395.                                 case 's':
  396.                                         Sflag = TRUE; break;
  397.                                 case 'v':
  398.                                 case 'V':
  399.                                         vflag = TRUE; break;
  400.                                 case 'n':
  401.                                 case 'N':
  402.                                         nflag = TRUE; break;
  403.                                 case 'm':
  404.                                 case 'M':
  405.                                         mflag = TRUE; break;
  406.                                 case 't':
  407.                                 case 'T':
  408.                                         tflag = TRUE; break;
  409.                                 case 'f':
  410.                                 case 'F':
  411.                                         fflag = TRUE; break;
  412.                                 case 'p':
  413.                                 case 'P':
  414.                                         pflag = TRUE; break;
  415.                                 case 'o':
  416.                                 case 'O':
  417.                                         output = cmdv[++i];
  418.                                         endopt = TRUE;
  419.                                         break;
  420.                                 /*
  421.                                  * Options for other passes.
  422.                                  */
  423.                                 case 'I':       /* compiler options */
  424.                                 case 'D':
  425.                                 case 'U':
  426.                                         hccopt[hcc_cnt++] = cmdv[i];
  427.                                         endopt = TRUE;
  428.                                         break;
  429.                                 default:
  430.                                         usage();
  431.                                         myexit(1);
  432.                                 }
  433.                         }
  434.                 } else {                /* input file */
  435.                         if (output == NULL)
  436.                                 output = chsuf(cmdv[i], ".ttp");
  437.  
  438.                         keepfile(cmdv[i]);
  439.                 }
  440.         }
  441.  
  442.         if ((ncfiles + nsfiles) > 1)
  443.                 domsg = TRUE;
  444.  
  445.         doinit();
  446.  
  447.         if (vflag)
  448.                 printf("%s\n", Version);
  449.  
  450.         for (i = 0; i < ncfiles ;i++) {
  451.                 if (domsg)
  452.                         printf("%s:\n", cfiles[i]);
  453.                 docomp(cfiles[i]);
  454.                 doopt(cfiles[i]);
  455.                 doasm(cfiles[i], TRUE);
  456.         }
  457.  
  458.         for (i = 0; i < nsfiles ;i++) {
  459.                 if (domsg)
  460.                         printf("%s:\n", sfiles[i]);
  461.                 doasm(sfiles[i], FALSE);
  462.         }
  463.  
  464.         dold();         /* run the loader */
  465.  
  466.         myexit(0);
  467. }
  468.  
  469. /*
  470.  * doinit() - set up some variables before getting started
  471.  */
  472. doinit()
  473. {
  474.         path = DEFPATH;
  475.         lib = DEFLIB;
  476.         tmp = DEFTMP;
  477. }
  478.  
  479. /*
  480.  * keepfile(f) - remember the filename 'f' in the appropriate place
  481.  */
  482. keepfile(f)
  483. char    *f;
  484. {
  485.         char    *p, *strchr();
  486.  
  487.         if ((p = strchr(f, '.')) == NULL) {     /* no suffix */
  488.                 lfiles[nlfiles++] = f;
  489.                 return;
  490.         }
  491.  
  492.         if (strcmp(p, ".c") == 0) {
  493.                 cfiles[ncfiles++] = f;
  494.                 return;
  495.         }
  496.         if (strcmp(p, ".s") == 0) {
  497.                 sfiles[nsfiles++] = f;
  498.                 return;
  499.         }
  500.         if (strcmp(p, ".o") == 0) {
  501.                 ofiles[nofiles++] = f;
  502.                 return;
  503.         }
  504.         if (strcmp(p, ".a") == 0) {
  505.                 lfiles[nlfiles++] = f;
  506.                 return;
  507.         }
  508.         if (strcmp(p, ".lib") == 0) {
  509.                 lfiles[nlfiles++] = f;
  510.                 return;
  511.         }
  512.         fprintf(stderr, "cc: unknown file suffix '%s'\n", f);
  513.         myexit(1);
  514. }
  515.  
  516. /*
  517.  * chsuf(f, suf) - change the suffix of file 'f' to 'suf'.
  518.  *
  519.  * Space for the new string is obtained using malloc().
  520.  */
  521. char *
  522. chsuf(f, suf)
  523. char    *f;
  524. char    *suf;
  525. {
  526.         char    *malloc();
  527.         char    *s, *p;
  528.  
  529.         p = s = malloc(strlen(f) + strlen(suf) + 1);
  530.  
  531.         strcpy(p, f);
  532.  
  533.         for (; *p ; p++) {
  534.                 if (*p == '.')
  535.                         break;
  536.         }
  537.  
  538.         while (*suf)
  539.                 *p++ = *suf++;
  540.  
  541.         *suf = '\0';
  542.  
  543.         return s;
  544. }
  545.  
  546. /*
  547.  * isfile(f) - return true if the given file exists
  548.  */
  549. int
  550. isfile(f)
  551. char    *f;
  552. {
  553.         int     fd;
  554.  
  555.         if ((fd = open(f, O_RDONLY)) < 0)
  556.                 return FALSE;
  557.  
  558.         close(fd);
  559.         return TRUE;
  560. }
  561.  
  562. /*
  563.  * findfile(e, b, s, chknul)
  564.  *
  565.  * Finds a file in one of the directories given in the environment
  566.  * variable whose value is pointed to by 'e'. Looks for the file
  567.  * given by 'b' with one of the suffixes listed in 's'. The suffix
  568.  * string should contain suffixes delimited by commas.
  569.  *
  570.  * e.g.  findfile("env stuff", "hcc", ".tos,.ttp,.prg")
  571.  *
  572.  * Returns a pointer to a static area containing the pathname of the
  573.  * file, if found, NULL otherwise.
  574.  *
  575.  * If 'chknul' is set, try the base name without any suffix as well.
  576.  */
  577. char *
  578. findfile(e, b, s, chknul)
  579. char    *e;
  580. char    *b;
  581. char    *s;
  582. int     chknul;
  583. {
  584.         static  char    file[256];
  585.         char    env[256];
  586.         char    suf[128];
  587.         char    *eptr, *sptr;
  588.         char    *p;
  589.  
  590.         /*
  591.          * Make a copy of the value of the env. variable. Convert all
  592.          * delimiters to nulls.
  593.          */
  594.         if (e != NULL) {
  595.                 strcpy(env, e);
  596.                 for (p = env; *p ;p++) {
  597.                         if (*p == ';' || *p == ',')
  598.                                 *p = '\0';
  599.                 }
  600.                 p[1] = '\0';            /* double null terminator */
  601.         } else
  602.                 env[1] = env[0] = '\0';
  603.  
  604.         strcpy(suf, s);
  605.         for (p = suf; *p ;p++) {
  606.                 if (*p == ',')
  607.                         *p = '\0';
  608.         }
  609.         p[1] = '\0';            /* double null terminator */
  610.  
  611.         /*
  612.          * Always check the root of the current drive and the
  613.          * current directory first. If that doesn't work, then
  614.          * start looking in the usual places...
  615.          */
  616.         for (sptr = suf; *sptr ;) {
  617.  
  618.                 sprintf(file, "%s%s", b, sptr);
  619.  
  620.                 if (isfile(file))
  621.                         return file;
  622.  
  623.                 sprintf(file, "\\%s%s", b, sptr);
  624.  
  625.                 if (isfile(file))
  626.                         return file;
  627.  
  628.                 while (*sptr++ != '\0')
  629.                         ;
  630.         }
  631.  
  632.         for (eptr = env; *eptr ;) {
  633.                 if (chknul) {
  634.                         sprintf(file, "%s\\%s", eptr, b);
  635.                         if (isfile(file))
  636.                                 return file;
  637.                 }
  638.  
  639.                 for (sptr = suf; *sptr ;) {
  640.  
  641.                         sprintf(file, "%s\\%s%s", eptr, b, sptr);
  642.  
  643.                         if (isfile(file))
  644.                                 return file;
  645.  
  646.                         while (*sptr++ != '\0')
  647.                                 ;
  648.                 }
  649.                 while (*eptr++ != '\0')
  650.                         ;
  651.         }
  652.         return NULL;            /* give up */
  653. }
  654.  
  655. /*
  656.  * docmd(path, cmdline) - run a command
  657.  */
  658. int
  659. docmd(path, cmdline)
  660. char    *path;
  661. char    *cmdline;
  662. {
  663.         int     i;
  664.         char    cmd[150];
  665.  
  666.         strcpy(&cmd[1], cmdline);
  667.         cmd[0] = strlen(cmdline);
  668.  
  669.         i = Pexec(0, path, cmd, 0L);
  670.  
  671.         return i;
  672. }
  673.  
  674. /*
  675.  * docomp(f) - run the compiler on the given .c file
  676.  */
  677. docomp(f)
  678. char    *f;
  679. {
  680.         int     i;
  681.         char    *cpath, *sf;
  682.  
  683.         if ((cpath = findfile(path, CC, EXSUF, FALSE)) == NULL) {
  684.                 fprintf(stderr, "cc: can't find compiler program '%s'\n", CC);
  685.                 myexit(1);
  686.         }
  687.  
  688.         strcpy(cmdln, pflag ? "-P " : "");
  689.  
  690.         for (i=0; i < hcc_cnt ;i++) {
  691.                 strcat(cmdln, hccopt[i]);
  692.                 strcat(cmdln, " ");
  693.         }
  694.         strcat(cmdln, f);
  695.  
  696.         if (nflag || vflag)
  697.                 fprintf(stderr, "%s %s\n", cpath, cmdln);
  698.  
  699.         if (!nflag) {
  700.                 if (docmd(cpath, cmdln)) {
  701.                         sf = chsuf(f, ".s");
  702.                         unlink(sf);
  703.                         free(sf);
  704.                         fprintf(stderr, "cc: compiler failed\n");
  705.                         myexit(1);
  706.                 }
  707.         }
  708. }
  709.  
  710. /*
  711.  * doopt(f) - run the optimizer
  712.  *
  713.  * Only optimize files that were produced by the compiler.
  714.  */
  715. doopt(f)
  716. char    *f;
  717. {
  718.         int     i;
  719.         char    *opath;
  720.         char    *sf;
  721.  
  722.         if (!Oflag)
  723.                 return;
  724.  
  725.         if ((opath = findfile(path, OPT, EXSUF, FALSE)) == NULL) {
  726.                 fprintf(stderr, "cc: can't find optimizer program '%s'\n", OPT);
  727.                 myexit(1);
  728.         }
  729.  
  730.         sf = chsuf(f, ".s");
  731.  
  732.         if (nflag || vflag)
  733.                 fprintf(stderr, "%s %s %s\n",
  734.                         opath, sf, OTMP);
  735.  
  736.         if (!nflag) {
  737.                 sprintf(cmdln, "%s %s", sf, OTMP);
  738.                 if (docmd(opath, cmdln)) {
  739.                         unlink(OTMP);
  740.                         fprintf(stderr, "cc: optimizer failed (continuing)\n");
  741.                         unlink(OTMP);
  742.                 } else {
  743.                         unlink(sf);
  744.                         rename(OTMP, sf);
  745.                 }
  746.         }
  747.         free(sf);
  748. }
  749.  
  750. /*
  751.  * doasm() - run the assembler
  752.  *
  753.  * If 'istmp' is TRUE, the file we were given is a temporary
  754.  */
  755. doasm(f, istmp)
  756. char    *f;
  757. int     istmp;
  758. {
  759.         char    *strrchr();
  760.         int     i;
  761.         char    apath[128], *dpath;
  762.         char    *s;
  763.         char    *sf;
  764.  
  765.         if (Sflag)
  766.                 return;
  767.  
  768.         if ((dpath = findfile(path, ASM, EXSUF, FALSE)) == NULL) {
  769.                 fprintf(stderr, "cc: can't find assembler program '%s'\n", ASM);
  770.                 myexit(1);
  771.         }
  772.         strcpy(apath, dpath);
  773.  
  774.         dpath = NULL;
  775.  
  776.         sf = chsuf(f, ".s");
  777.  
  778.         if (nflag || vflag)
  779.                 fprintf(stderr, "%s -l -u%s%s %s\n",
  780.                         apath,
  781.                         (dpath != NULL) ? " -s " : "",
  782.                         (dpath != NULL) ? dpath : "",
  783.                         sf);
  784.  
  785.         if (!nflag) {
  786.                 sprintf(cmdln, "%s%s %s",
  787.                         (dpath != NULL) ? "-l -u -s " : "",
  788.                         (dpath != NULL) ? dpath : "",
  789.                         sf);
  790.  
  791.                 if (docmd(apath, cmdln)) {
  792.                         fprintf(stderr, "cc: assembler failed '%s'\n",
  793.                                 sf);
  794.                         if (istmp)
  795.                                 unlink(sf);
  796.                         free(sf);
  797.                         myexit(1);
  798.                 }
  799.         }
  800.  
  801.         if (nflag) {
  802.                 free(sf);
  803.                 return;
  804.         }
  805.  
  806.         if (istmp)
  807.                 unlink(sf);
  808.  
  809.         free(sf);
  810. }
  811.  
  812. /*
  813.  * dold() - run the loader
  814.  */
  815. dold()
  816. {
  817.         FILE    *fp, *fopen();
  818.         int     i;
  819.         char    tfile[128];
  820.         char    *lpath;
  821.         char    *s;
  822.         char    *l;
  823.  
  824.         if (cflag || Sflag)
  825.                 return;
  826.  
  827.         /*
  828.          * Construct the name of the loader data file.
  829.          */
  830.         if (*tmp != '\0') {
  831.                 strcpy(tfile, tmp);
  832.                 if (tfile[strlen(tfile)-1] != '\\')
  833.                         strcat(tfile, "\\");
  834.         } else
  835.                 tfile[0] = '\0';
  836.  
  837.         strcat(tfile, LTMP);
  838.  
  839.         unlink(tfile);
  840.         /*
  841.          * Construct loader command file
  842.          */
  843.         if ((fp = fopen(tfile, "w")) == NULL) {
  844.                 fprintf(stderr, "cc: can't open loader temp file\n");
  845.                 myexit(1);
  846.         }
  847.  
  848.         l = pflag ? PCSU : CSU;
  849.         if ((lpath = findfile(lib, l, "", TRUE)) == NULL) {
  850.                 fprintf(stderr, "cc: can't find C startup code '%s'\n", l);
  851.                 myexit(1);
  852.         }
  853.         fprintf(fp, "%s\n", lpath);
  854.  
  855.         for (i = 0; i < ncfiles ;i++) {
  856.                 s = chsuf(cfiles[i], ".o");
  857.                 fprintf(fp, "%s\n", s);
  858.                 free(s);
  859.         }
  860.         for (i = 0; i < nsfiles ;i++) {
  861.                 s = chsuf(sfiles[i], ".o");
  862.                 fprintf(fp, "%s\n", s);
  863.                 free(s);
  864.         }
  865.         for (i = 0; i < nofiles ;i++)
  866.                 fprintf(fp, "%s\n", ofiles[i]);
  867.  
  868.         for (i = 0; i < nlfiles ;i++) {
  869.                 if (isfile(lfiles[i])) {
  870.                         fprintf(fp, "%s\n", lfiles[i]);
  871.                 } else {
  872.                         lpath = findfile(lib, lfiles[i], LIBSUF, TRUE);
  873.                         if (lpath == NULL) {
  874.                                 fprintf(stderr, "cc: can't find library '%s'\n", lfiles[i]);
  875.                                 myexit(1);
  876.                         }
  877.                         fprintf(fp, "%s\n", lpath);
  878.                 }
  879.         }
  880.  
  881.         if (fflag) {
  882.                 l = pflag ? PLIBM : LIBM;
  883.                 if ((lpath = findfile(lib, l, LIBSUF, TRUE)) == NULL) {
  884.                         fprintf(stderr, "cc: can't find floating point library '%s'\n",l);
  885.                         myexit(1);
  886.                 }
  887.                 fprintf(fp, "%s\n", lpath);
  888.         }
  889.  
  890.         l = pflag ? PLIBC : LIBC;
  891.         if ((lpath = findfile(lib, l, LIBSUF, TRUE)) == NULL) {
  892.                 fprintf(stderr, "cc: can't find C runtime library '%s'\n", l);
  893.                 myexit(1);
  894.         }
  895.         fprintf(fp, "%s\n", lpath);
  896.  
  897.         fclose(fp);
  898.  
  899.         if ((lpath = findfile(path, LD, EXSUF, FALSE)) == NULL) {
  900.                 fprintf(stderr, "cc: can't find loader program '%s'\n", LD);
  901.                 myexit(1);
  902.         }
  903.  
  904.         sprintf(cmdln, "%s%s-p -u _main %s -o %s -f %s",
  905.                 mflag ? "-m " : "",
  906.                 tflag ? "-t " : "",
  907.                 fflag ? "-u __printf -u __scanf " : "",
  908.                 output,
  909.                 tfile);
  910.  
  911.         if (nflag || vflag)
  912.                 fprintf(stderr, "%s %s\n", lpath, cmdln);
  913.  
  914.         if (!nflag) {
  915.                 if (docmd(lpath, cmdln)) {
  916.                         fprintf(stderr, "cc: loader failed\n");
  917.                         unlink(tfile);
  918.                         unlink(output);
  919.                         myexit(1);
  920.                 }
  921.         }
  922.  
  923.         if (nflag)
  924.                 return;
  925.  
  926.         for (i = 0; i < ncfiles ;i++) {
  927.                 s = chsuf(cfiles[i], ".o");
  928.                 unlink(s);
  929.                 free(s);
  930.         }
  931.  
  932.         for (i = 0; i < nsfiles ;i++) {
  933.                 s = chsuf(sfiles[i], ".o");
  934.                 unlink(s);
  935.                 free(s);
  936.         }
  937.  
  938.         unlink(tfile);
  939. }
  940.